/*********************************************************************************
 *      Copyright:  (C) 2022 dairongan<2974932606@qq.com>
 *                  All rights reserved.
 *
 *       Filename:  oled_api.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(07/27/2022)
 *         Author:  dairongan <2974932606@qq.com>
 *      ChangeLog:  1, Release initial version on "07/27/2022 07:42:03 PM"
 *                 
 ********************************************************************************/
#include <sys/ioctl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include "oledfont.h"
#include "oled_api.h"
#include "logger.h"

//坐标设置
void OLED_Set_Pos(int fd,unsigned char x, unsigned char y) 
{ 	
	ioctl(fd,OLED_CMD,0xb0+y);
	ioctl(fd,OLED_CMD,((x&0xf0)>>4)|0x10);
	ioctl(fd,OLED_CMD,(x&0x0f)); 
}   	  
//开启OLED显示    
void OLED_Display_On(int fd)
{
	ioctl(fd,OLED_CMD,0X8D);  //SET DCDC命令
	ioctl(fd,OLED_CMD,0X14);  //DCDC ON
	ioctl(fd,OLED_CMD,0XAF);  //DISPLAY ON
}
//关闭OLED显示     
void OLED_Display_Off(int fd)
{
	ioctl(fd,OLED_CMD,0X8D);  //SET DCDC命令
	ioctl(fd,OLED_CMD,0X10);  //DCDC OFF
	ioctl(fd,OLED_CMD,0XAE);  //DISPLAY OFF
}		   			 
//注意：清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!	  
void OLED_Clear(int fd)  
{  
	uint8_t i,n;		    
	for(i=0;i<8;i++)  
	{  
		ioctl (fd,OLED_CMD,0xb0+i);    //设置页地址（0~7）
		ioctl (fd,OLED_CMD,0x00);      //设置显示位置—列低地址
		ioctl (fd,OLED_CMD,0x10);      //设置显示位置—列高地址   
		for(n=0;n<128;n++)
			ioctl(fd,OLED_DATA,0); 
	} //更新显示
}
void OLED_On(int fd)  
{  
	uint8_t i,n;		    
	for(i=0;i<8;i++)  
	{  
		ioctl (fd,OLED_CMD,0xb0+i);    //设置页地址（0~7）
		ioctl (fd,OLED_CMD,0x00);      //设置显示位置—列低地址
		ioctl (fd,OLED_CMD,0x10);      //设置显示位置—列高地址   
		for(n=0;n<128;n++)ioctl(fd,OLED_DATA,1); 
	} //更新显示
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//				 
//size:选择字体 16/12 
void OLED_ShowChar(int fd,uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size)
{      	
	unsigned char c=0,i=0;	
	unsigned long xy=0;
	xy=x*10+y;
	c=chr-' ';//得到偏移后的值			
	if(x>Max_Column-1){x=0;y=y+2;xy=10*x+y;}
	if(Char_Size ==16)
	{
		ioctl(fd,OLED_SETPOS,xy);	
		for(i=0;i<8;i++)
			ioctl(fd,OLED_DATA,F8X16[c*16+i]);
			ioctl(fd,OLED_SETPOS,xy+1);
		for(i=0;i<8;i++)
			ioctl(fd,OLED_DATA,F8X16[c*16+i+8]);
	}
	else 
	{	
		ioctl(fd,OLED_SETPOS,xy);
		for(i=0;i<6;i++)
			ioctl(fd,OLED_DATA,F6x8[c][i]);
	}
}
 
//显示一个字符号串
void OLED_ShowString(int fd,uint8_t x,uint8_t y,uint8_t *chr,uint8_t Char_Size)
{
	unsigned char j=0;
	while (chr[j]!='\0')
	{		
		OLED_ShowChar(fd,x,y,chr[j],Char_Size);
		x+=8;
		if(x>120)
		{
			x=0;y+=2;
		}
		j++;
	}
}
//显示汉字
void OLED_ShowCHinese(int fd,uint8_t x,uint8_t y,uint8_t no)
{      			    
	uint8_t t,adder=0;
	unsigned long xy=0;
	xy=10*x+y;
	ioctl(fd,OLED_SETPOS,xy);	
	for(t=0;t<16;t++)
	{
		ioctl(fd,OLED_DATA,Hzk[2*no][t]);
		adder+=1;
	}	
	ioctl(fd,OLED_SETPOS,xy+1);	
	for(t=0;t<16;t++)
	{	
		ioctl(fd,OLED_DATA,Hzk[2*no+1][t]);
		adder+=1;
	}					
}
/***********功能描述：显示显示BMP图片128×64起始点坐标(x,y),x的范围0～127，y为页的范围0～7*****************/
void OLED_DrawBMP(int fd,unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[])
{ 	
	unsigned int j=0;
	unsigned char x,y;
	unsigned long x0y=0;

	if(y1%8==0) y=y1/8;      
	else y1=y/8+1;
	for(y=y0;y<y1;y++)
	{
		x0y=x0*10+y;
		ioctl(fd,OLED_SETPOS,x0y);
		for(x=x0;x<x1;x++)
		{      
			ioctl(fd,OLED_DATA,BMP[j++]);	    	
		}
	}
} 
//初始化OLED			    
void OLED_Init(int fd)
{ 	
	usleep(200000);
	ioctl(fd,OLED_CMD,0xAE);//关闭显示

	ioctl(fd,OLED_CMD,0x00);//---set low column address
	ioctl(fd,OLED_CMD,0x10);//---set high column address

	ioctl(fd,OLED_CMD,0x40);//-not offset

	ioctl(fd,OLED_CMD,0x81);//设置对比度
	ioctl(fd,OLED_CMD,0xcf);

	ioctl(fd,OLED_CMD,0xa1);//段重定向设置

	ioctl(fd,OLED_CMD,0xc8);//

	ioctl(fd,OLED_CMD,0xa6);//设置驱动路数
	ioctl(fd,OLED_CMD,0xA8);

	ioctl(fd,OLED_CMD,0x3F);
	ioctl(fd,OLED_CMD,0xD3);

	ioctl(fd,OLED_CMD,0x00);
	ioctl(fd,OLED_CMD,0xD5);

	ioctl(fd,OLED_CMD,0x80);
	ioctl(fd,OLED_CMD,0xD9);

	ioctl(fd,OLED_CMD,0xF1);
	ioctl(fd,OLED_CMD,0xDA);

	ioctl(fd,OLED_CMD,0x12);
	ioctl(fd,OLED_CMD,0xDB);

	ioctl(fd,OLED_CMD,0x40);
	ioctl(fd,OLED_CMD,0x20);

	ioctl(fd,OLED_CMD,0x02);
	ioctl(fd,OLED_CMD,0x8D);
	ioctl(fd,OLED_CMD,0X14);

	ioctl(fd,OLED_CMD,0xA4);
	ioctl(fd,OLED_CMD,0xA6);

	OLED_Clear(fd);
	ioctl(fd,OLED_CMD,0XAF);
} 

void * get_time()
{
    time_t      now;
    struct tm   *tt;

    now = time(NULL);
    tt= localtime(&now);
    return tt;
}


void OLED_updateTime(int fd)
{
	struct tm *timer;
	unsigned char date[16]={0};
	static int min=-1,mday=-1;

	timer = get_time();

	if(timer->tm_min!=min)
	{
		memset(date,0,sizeof(date));
		snprintf(date,16,"%02d:%02d",timer->tm_hour,timer->tm_min);
		OLED_ShowString(fd,87,0,date,16);
		min=timer->tm_min;
	}

	if(timer->tm_mday!=mday)
	{
		memset(date,0,sizeof(date));
		snprintf(date,16,"%04d-%02d-%02d",timer->tm_year+1900,timer->tm_mon+1,timer->tm_mday);
		OLED_ShowString(fd,0,0,date,16);
		mday=timer->tm_mday;
	}
	
}
